#pragma once
#include "LastBlockHandler.h"
#include "LastBlockEncryption.h"
#include "LastBlockDecryption.h"

namespace AppliedCryptography
{
	namespace AC = AppliedCryptography;

	template<unsigned int TKeySize, unsigned int TBlockSize>
	class TruncatePadding
	{
	private:
		class _default : public AC::LastBlockHandler<TKeySize, TBlockSize>
		{
			public:
				virtual AC::Block<TBlockSize> Process(
					const AC::Cryptor<TKeySize,TBlockSize>& cryptor, 
					const AC::Block<TBlockSize>& last /* Plaintext */, 
					unsigned int lastBlockLength,
					AC::Block<TBlockSize>& secondToLast /* Should be encrypted once */) const
				{
					AC::Block<TBlockSize> chyper;
					AC::Block<TBlockSize> xord;

					cryptor.Process(secondToLast, chyper);

					xord = chyper ^ last;

					for(unsigned int i=0; i < TBlockSize-lastBlockLength; i++)
						xord[lastBlockLength+i] = 0;

					return xord;
				};
		};
	public:
		class Encryption : public AC::LastBlockEncryption<TKeySize, TBlockSize>
		{
		private:
			typename TruncatePadding<TKeySize, TBlockSize>::_default _lbh;
		public:
			public:
				virtual AC::Block<TBlockSize> Process(
					const AC::Cryptor<TKeySize,TBlockSize>& cryptor, 
					const AC::Block<TBlockSize>& last /* Plaintext */, 
					unsigned int lastBlockLength,
					AC::Block<TBlockSize>& secondToLast /* Should be encrypted once */) const
				{
					return _lbh.Process(cryptor, last, lastBlockLength, secondToLast);
				};
		};

		class Decryption : public AC::LastBlockDecryption<TKeySize, TBlockSize>
		{
		private:
			typename TruncatePadding<TKeySize, TBlockSize>::_default _lbh;
		public:
			public:
				virtual AC::Block<TBlockSize> Process(
					const AC::Cryptor<TKeySize,TBlockSize>& cryptor, 
					const AC::Block<TBlockSize>& last /* Plaintext */, 
					unsigned int lastBlockLength,
					AC::Block<TBlockSize>& secondToLast /* Should be encrypted once */) const
				{
					return _lbh.Process(cryptor, last, lastBlockLength, secondToLast);
				};
		};
	};
};
